package com.athenaeum.dataxplore.controller;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.athenaeum.datastore.domain.Department;
import com.athenaeum.datastore.domain.Organization;
import com.athenaeum.datastore.domain.Project;
import com.athenaeum.datastore.domain.User;
import com.athenaeum.datastore.domain.UserGroup;
import com.athenaeum.datastore.service.DepartmentService;
import com.athenaeum.datastore.service.OrganizationService;
import com.athenaeum.datastore.service.ProjectService;
import com.athenaeum.datastore.service.UserService;

@Controller
public class AccountController {

	private static final Logger log = LoggerFactory
			.getLogger(AccountController.class);
	@Autowired
	private OrganizationService organizationService;

	@Autowired
	private DepartmentService departmentService;

	@Autowired
	private ProjectService projectService;

	@Autowired
	private UserService userService;

	@RequestMapping(value = "/account/organization/index", method = RequestMethod.GET)
	public String organization(Locale locale, Model model) {
		log.info("Loading Settings - Organization - Create Page...");
		model.addAttribute("organization", new Organization());
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		return "account/organization/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/edit", method = RequestMethod.GET)
	public String editOrganization(
			@PathVariable("organizationid") String organizationId,
			Locale locale, Model model) {
		log.info("Loading Settings - Organization - Edit Page...");
		model.addAttribute("organization",
				organizationService.findOne(organizationId));
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		return "account/organization/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/delete", method = RequestMethod.GET)
	public String deleteOrganization(
			@PathVariable("organizationid") String organizationId,
			Locale locale, Model model) {
		log.info("Loading Settings - Organization - Delete Action...");
		organizationService.delete(organizationId);
		return "redirect:/settings/organizations";
	}

	@RequestMapping(value = "/account/organization/save", method = RequestMethod.POST)
	public String saveDepartment(Locale locale,
			@ModelAttribute("organization") Organization organization,
			BindingResult result, Model model) {
		log.info("Saving Settings - Organization - Save Page...");
		if (result.hasErrors())
			return "account/organization/index";
		organization = organizationService.save(organization);
		return "redirect:/account/organization/" + organization.getId()
				+ "/department/index/";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/index", method = RequestMethod.GET)
	public String departments(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId) {
		log.info("Loading Settings - Department - Create Page...");
		model.addAttribute("department", new Department());
		model.addAttribute("organizationid", organizationId);
		Organization organization = organizationService.findOne(organizationId);
		model.addAttribute("departments", organization.getDepartments()
				.values());
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		return "account/department/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/edit", method = RequestMethod.GET)
	public String editDepartment(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId) {
		log.info("Loading Settings - Department - Edit Page...");
		model.addAttribute("department",
				departmentService.findOne(departmentId));
		model.addAttribute("organizationid", organizationId);
		Organization organization = organizationService.findOne(organizationId);
		model.addAttribute("departments", organization.getDepartments()
				.values());
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		return "account/department/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/delete", method = RequestMethod.GET)
	public String deleteDepartment(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId) {
		log.info("Loading Settings - Department - Delete Action...");

		Organization organization = organizationService.findOne(organizationId);
		Department department = departmentService.findOne(departmentId);
		Map<String, Department> departments = organization.getDepartments();
		departments.remove(department.getId());
		organization.setDepartments(departments);
		organization = organizationService.save(organization);
		return "redirect:/account/organization/" + organizationId
				+ "/department/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/save", method = RequestMethod.POST)
	public String saveDepartment(Locale locale,
			@ModelAttribute("department") Department department,
			@PathVariable("organizationid") String organizationId,
			BindingResult result, Model model) {
		log.info("Saving Settings - Department - Save Page...");
		if (result.hasErrors())
			return "account/organization/" + organizationId
					+ "/department//index";
		Organization organization = organizationService.findOne(organizationId);
		Map<String, Department> departments;
		if (CollectionUtils.isEmpty(organization.getDepartments().values()))
			departments = new HashMap<String, Department>();
		else
			departments = organization.getDepartments();
		departments.put(department.getId(), department);
		organization.setDepartments(departments);

		organization = organizationService.save(organization);
		return "redirect:/account/organization/" + organizationId
				+ "/department/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/index", method = RequestMethod.GET)
	public String project(
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId, Locale locale,
			Model model) {
		log.info("Loading Settings - Project - Create Page...");
		model.addAttribute("project", new Project());
		model.addAttribute("organizationid", organizationId);
		model.addAttribute("departmentid", departmentId);
		Department department = departmentService.findOne(departmentId);
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		model.addAttribute("projects", department.getProjects().values());
		return "account/project/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/{projectid}/edit", method = RequestMethod.GET)
	public String editProject(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId,
			@PathVariable("projectid") String projectId) {
		log.info("Loading Settings - Project - Edit Page...");
		model.addAttribute("project", projectService.findOne(projectId));
		model.addAttribute("organizationid", organizationId);
		model.addAttribute("departmentid", departmentId);
		Department department = departmentService.findOne(departmentId);
		model.addAttribute("projects", department.getProjects().values());
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		return "account/project/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/{projectid}/delete", method = RequestMethod.GET)
	public String deleteProject(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId,
			@PathVariable("projectid") String projectId) {
		log.info("Loading Settings - Project - Delete Action...");

		Department department = departmentService.findOne(departmentId);
		Project project = projectService.findOne(projectId);
		project.getUsers().clear();
		project = projectService.save(project);
		Map<String, Project> projects = department.getProjects();
		projects.remove(project.getId());
		department.setProjects(projects);
		department = departmentService.save(department);
		return "redirect:/account/organization/" + organizationId
				+ "/department/" + departmentId + "/project/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/save", method = RequestMethod.POST)
	public String saveProject(Locale locale,
			@ModelAttribute("project") Project project,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId,
			BindingResult result, Model model) {
		log.info("Saving Settings - Project - Save Page...");
		if (result.hasErrors())
			return "account/organization/" + organizationId + "/department/"
					+ departmentId + "/project/index";
		Department department = departmentService.findOne(departmentId);
		Map<String, Project> projects;
		if (CollectionUtils.isEmpty(department.getProjects().values()))
			projects = new HashMap<String, Project>();
		else
			projects = department.getProjects();
		projects.put(project.getId(), project);
		department.setProjects(projects);

		department = departmentService.save(department);
		return "redirect:/account/organization/" + organizationId
				+ "/department/" + departmentId + "/project/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/{projectid}/user/index", method = RequestMethod.GET)
	public String team(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId,
			@PathVariable("projectid") String projectId) {
		log.info("Loading Settings - Team - Create Page...");
		model.addAttribute("usergroup", new UserGroup());
		model.addAttribute("organizationid", organizationId);
		model.addAttribute("departmentid", departmentId);
		model.addAttribute("projectid", projectId);
		Map<String, String> userMap = new LinkedHashMap<String, String>();
		for (User user : userService.findAll())
			userMap.put(user.getId(), user.getFullName() + " (" + user.getId()
					+ ")");
		model.addAttribute("allusers", userMap);
		Project project = projectService.findOne(projectId);
		model.addAttribute("projectusers", project.getUsers().values());

		return "account/user/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/{projectid}/user/save", method = RequestMethod.POST)
	public String saveUser(Locale locale,
			@ModelAttribute("usergroup") UserGroup userGroup,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId,
			@PathVariable("projectid") String projectId, BindingResult result,
			Model model) {
		log.info("Saving Settings - User - Save Page...");
		if (result.hasErrors())
			return "account/organization/" + organizationId + "/department/"
					+ departmentId + "/project/" + projectId + "/user/index";
		Project project = projectService.findOne(projectId);
		Map<String, User> users = project.getUsers();
		for (String userId : userGroup.getUsers()) {
			User user = userService.findOne(userId);
			users.put(user.getId(), user);
		}
		project.setUsers(users);
		project = projectService.save(project);
		return "redirect:/account/organization/" + organizationId
				+ "/department/" + departmentId + "/project/" + projectId
				+ "/user/index";
	}

	@RequestMapping(value = "/account/organization/{organizationid}/department/{departmentid}/project/{projectid}/user/{userid}/delete", method = RequestMethod.GET)
	public String deleteUser(Locale locale, Model model,
			@PathVariable("organizationid") String organizationId,
			@PathVariable("departmentid") String departmentId,
			@PathVariable("projectid") String projectId,
			@PathVariable("userid") String userId) {
		log.info("Loading Settings - User - Delete Action...");
		Project project = projectService.findOne(projectId);
		User user = userService.findOne(userId);
		Map<String, User> users = project.getUsers();
		users.remove(user.getId());
		project.setUsers(users);
		project = projectService.save(project);
		return "redirect:/account/organization/" + organizationId
				+ "/department/" + departmentId + "/project/" + projectId
				+ "/user/index";
	}
}
